package com.qd.panda.service.third.hk;

import com.cdqidi.config.mybatis.handler.GeoPoint;
import com.cdqidi.constant.ConstantDto;
import com.cdqidi.exception.ApiException;
import com.qd.common.panda.constant.PandaConstant;
import com.qd.common.sys.constant.Constants;
import com.qd.hik.dto.HkBaseHttpResp;
import com.qd.hik.dto.parkinfo.HkParkInfoResp;
import com.qd.hik.dto.parkinfo.HkParkParentResp;
import com.qd.hik.dto.parkinfo.HkParkReq;
import com.qd.hik.service.HkParkInfoService;
import com.qd.panda.model.CarPark;
import com.qd.panda.model.CarParkLocation;
import com.qd.panda.model.CarParkTime;
import com.qd.panda.service.park.*;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

/**
 * 停车场数据同步
 *
 * @author sjk
 * @create 2024-05-31 14:20
 * @since 1.0.0
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class HkParkSyncService {
    private final CarParkService carParkService;
    private final CarParkTimeService carParkTimeService;
    private final CarParkLocationService carParkLocationService;
    private final CarParkFeeService carParkFeeService;
    private final HkParkInfoService hkParkInfoService;
    private final ParkHolderService parkHolderService;
//    private final BufferedWriter writer = FileUtil.getWriter(new File("d://1.txt"), Charset.defaultCharset(), true);

    /**
     * 同步停车场数据
     *
     * @param hkParkReq 查询条件
     * @param now       时间
     */
    @SneakyThrows
    @Transactional(rollbackFor = Exception.class)
    public void parks(HkParkReq hkParkReq, LocalDateTime now) {
        HkBaseHttpResp<HkParkParentResp> parks = hkParkInfoService.parks(hkParkReq);
        if (parks.isSuccess()) {
            List<HkParkInfoResp> results = parks.getData().getResults();
            if (null == results || results.isEmpty()) {
                return;
            }
            log.info("同步海康停车场数据,页数: {},条数: {}", hkParkReq.getPageNo(), results.size());
//            for (HkParkInfoResp result : results) {
//                writer.append(result.getParkCode()).append(" ").append(result.getParkName()).append(" ").append(result.getParkType()+"").append("\r\n");
//            }
//            writer.flush();
            saveParks(results, now);
            hkParkReq.setPageNo(hkParkReq.getPageNo() + 1);
            parks(hkParkReq, now);
        } else {
            throw new ApiException(Optional.ofNullable(parks.getMsg()).orElse("同步海康停车场数据异常"));
        }
    }

    private void saveParks(List<HkParkInfoResp> results, LocalDateTime now) {
        List<CarPark> addCarParkList = new ArrayList<>(1000);
        List<CarPark> updateCarParkList = new ArrayList<>(1000);

        List<com.qd.panda.model.CarParkLocation> addLocationList = new ArrayList<>(1000);
        List<com.qd.panda.model.CarParkLocation> updateLocationList = new ArrayList<>(1000);

        List<CarParkTime> addTimeList = new ArrayList<>(1000);
        List<CarParkTime> updateTimeList = new ArrayList<>(1000);

        List<com.qd.panda.model.CarParkFee> addFeeList = new ArrayList<>(1000);
        List<com.qd.panda.model.CarParkFee> updateFeeList = new ArrayList<>(1000);

        for (HkParkInfoResp result : results) {
            CarPark carPark = carParkService.getById(result.getParkCode());
            if (null == carPark) {
                carPark = createCarPark(now, result);
                addCarParkList.add(carPark);

                addLocationList.add(createLocation(result, carPark));

                addTimeList.add(createParkTime(result, carPark));

                addFeeList.add(createParkFee(result, carPark));
            } else {
                updateCarPark(result, carPark, updateCarParkList);
                updateLocation(result, updateLocationList);
                updateTime(result, updateTimeList);
                updateFee(result, updateFeeList);
            }
        }

        if (!addCarParkList.isEmpty()) {
            carParkService.saveBatch(addCarParkList);
            addCarParkList.clear();
        }

        if (!updateCarParkList.isEmpty()) {
            carParkService.updateBatchIds(updateCarParkList);
            updateCarParkList.clear();
        }

        if (!addLocationList.isEmpty()) {
            carParkLocationService.saveBatch(addLocationList);
            addLocationList.clear();
        }

        if (!updateLocationList.isEmpty()) {
            carParkLocationService.updateBatchIds(updateLocationList);
            updateLocationList.clear();
        }

        if (!addTimeList.isEmpty()) {
            carParkTimeService.saveBatch(addTimeList);
            addTimeList.clear();
        }

        if (!updateTimeList.isEmpty()) {
            carParkTimeService.updateBatchIds(updateTimeList);
            updateTimeList.clear();
        }

        if (!addFeeList.isEmpty()) {
            carParkFeeService.saveBatch(addFeeList);
            addFeeList.clear();
        }

        if (!updateFeeList.isEmpty()) {
            carParkFeeService.updateBatchIds(updateFeeList);
            updateFeeList.clear();
        }

        for (HkParkInfoResp result : results) {
            carParkService.updateToRedis(result.getParkCode(), null, result.getTotalParkingSpaceNum(), result.getLeftParkingSpaceNum());
        }
    }

    private void updateFee(HkParkInfoResp result, List<com.qd.panda.model.CarParkFee> updateFeeList) {
        com.qd.panda.model.CarParkFee carParkFee = carParkFeeService.getUniqueByPId(result.getParkCode());
        if (null != carParkFee) {
            if (StringUtils.hasLength(carParkFee.getNote())) {
                if (!carParkFee.getNote().equals(result.getPayRuleDesc())) {
                    carParkFee.setNote(result.getPayRuleDesc());
                    updateFeeList.add(carParkFee);
                }
            } else {
                carParkFee.setNote(result.getPayRuleDesc());
                updateFeeList.add(carParkFee);
            }
        }
    }

    private void updateTime(HkParkInfoResp result, List<CarParkTime> updateTimeList) {
        CarParkTime carParkTime = carParkTimeService.getById(result.getParkCode());
        if (null != carParkTime) {
            boolean isUpdate = false;
            LocalTime startTime = LocalTime.parse(result.getParkingStartTime(), DateTimeFormatter.ISO_TIME);
            LocalTime endTime = LocalTime.parse(result.getParkingEndTime(), DateTimeFormatter.ISO_TIME);
            if (!carParkTime.getStartTime().equals(startTime)) {
                carParkTime.setStartTime(startTime);
                isUpdate = true;
            }
            if (!carParkTime.getEndTime().equals(endTime)) {
                carParkTime.setEndTime(endTime);
                isUpdate = true;
            }
            if (isUpdate) {
                updateTimeList.add(carParkTime);
            }
        }
    }

    private void updateLocation(HkParkInfoResp result, List<CarParkLocation> updateLocationList) {
        CarParkLocation carParkLocation = carParkLocationService.getById(result.getParkCode());
        if (null != carParkLocation) {
            boolean isUpdate = false;
            String parkingAddress = result.getParkingAddress();
            if (carParkLocation.getAddress().equals(parkingAddress)) {
                carParkLocation.setAddress(parkingAddress);
                isUpdate = true;
            }
//            GeoPointDTO geoPointDTO = GeoUtil.convertBD09ToGCJ02(new BigDecimal(result.getParkLatitude()).doubleValue(), new BigDecimal(result.getParkLongitude()).doubleValue());
            BigDecimal lat = new BigDecimal(result.getParkLatitude());
            BigDecimal lng = new BigDecimal(result.getParkLongitude());
            if (carParkLocation.getLat().compareTo(lat) != BigDecimal.ZERO.intValue()) {
                carParkLocation.setLat(lat);
                isUpdate = true;
            }
            if (carParkLocation.getLng().compareTo(lng) != BigDecimal.ZERO.intValue()) {
                carParkLocation.setLng(lng);
                isUpdate = true;
            }
            if (isUpdate) {
                carParkLocation.setLocation(new GeoPoint(carParkLocation.getLng(), carParkLocation.getLat()));
                updateLocationList.add(carParkLocation);
            }
        }
    }

    private void updateCarPark(HkParkInfoResp result, CarPark carPark, List<CarPark> updateCarParkList) {
        boolean isUpdate = false;
        if (!carPark.getName().equals(result.getParkName())) {
            carPark.setName(result.getParkName());
            isUpdate = true;
        }
        if (result.getParkType() == 1) {
            if (carPark.getOnStreet().equals(ConstantDto.SF0)) {
                carPark.setOnStreet(ConstantDto.SF1);
                isUpdate = true;
            }
        } else {
            if (carPark.getOnStreet().equals(ConstantDto.SF1)) {
                carPark.setOnStreet(ConstantDto.SF0);
                isUpdate = true;
            }
        }
        if (isUpdate) {
            updateCarParkList.add(carPark);
        }
    }

    private com.qd.panda.model.CarParkFee createParkFee(HkParkInfoResp result, CarPark carPark) {
        com.qd.panda.model.CarParkFee carParkFee = new com.qd.panda.model.CarParkFee();
        carParkFee.setPId(carPark.getPId());
//                carParkFee.setBillRule(billRule);
        carParkFee.setNote(result.getPayRuleDesc());
        return carParkFee;
    }

    private CarParkTime createParkTime(HkParkInfoResp result, CarPark carPark) {
        CarParkTime carParkTime = new CarParkTime();
        carParkTime.setPId(carPark.getPId());
        String startTime = getString(result.getParkingStartTime());
        String endTime = getString(result.getParkingEndTime());

        carParkTime.setStartTime(LocalTime.parse(startTime, DateTimeFormatter.ISO_TIME));
        carParkTime.setEndTime(LocalTime.parse(endTime, DateTimeFormatter.ISO_TIME));
        return carParkTime;
    }

    private static String getString(String time) {
        if (time.length() < 5) {
            log.info("time: {}", time);
            final String[] startTimeSplit = time.split(":");
            String hour = startTimeSplit[0];
            String minute = "00";
            if (startTimeSplit.length == 2) {
                minute = startTimeSplit[1];
            }
            if (hour.length() == 1) {
                hour = String.format("%02d", Integer.parseInt(hour));
            }
            if (minute.length() == 1) {
                minute = String.format("%02d", Integer.parseInt(minute));
            }
            time = hour + ":" + minute;
        }
        return time;
    }

    private com.qd.panda.model.CarParkLocation createLocation(HkParkInfoResp result, CarPark carPark) {
//        GeoPointDTO geoPointDTO = GeoUtil.convertBD09ToGCJ02(new BigDecimal(result.getParkLatitude()).doubleValue(), new BigDecimal(result.getParkLongitude()).doubleValue());
        BigDecimal lat = new BigDecimal(result.getParkLatitude());
        BigDecimal lng = new BigDecimal(result.getParkLongitude());
        com.qd.panda.model.CarParkLocation location = new com.qd.panda.model.CarParkLocation();
        location.setPId(carPark.getPId());
        location.setAddress(result.getParkingAddress());
        location.setLat(lat);
        location.setLng(lng);
        location.setLocationType(5);
        location.setLocation(new GeoPoint(location.getLng(), location.getLat()));
        return location;
    }

    private CarPark createCarPark(LocalDateTime now, HkParkInfoResp result) {
        CarPark carPark = new CarPark();
        carPark.setPId(result.getParkCode());
        carPark.setCode(parkHolderService.getCode(0));
        carPark.setName(result.getParkName());
        carPark.setParkNum(result.getTotalParkingSpaceNum());
        carPark.setIntroduce(result.getDescription());
        carPark.setCarParkType(PandaConstant.CAR_PARK_TYPE_1);
        carPark.setAddTime(now);
        carPark.setThirdPartyBill(ConstantDto.SF1);
        carPark.setConfirmIn(ConstantDto.SF0);
        carPark.setConfirmOut(ConstantDto.SF0);
        carPark.setOperator(Constants.ADMIN_DEFAULT_ID);
        carPark.setOrgId(Constants.DEFAULT_TREE_PARENT_ID);
        carPark.setEnable(ConstantDto.SF1);
        carPark.setParkType(PandaConstant.PARK_TYPE_CAR_PARK);
        carPark.setOwnBusiness(ConstantDto.SF0);
        if (result.getParkType() == 1) {
            //地面
            carPark.setOnStreet(ConstantDto.SF1);
        } else {
            carPark.setOnStreet(ConstantDto.SF0);
        }
        carPark.setParkSpaceType(PandaConstant.PARK_SPACE_TYPE2);
        carPark.setEtcPay(ConstantDto.SF0);
        carPark.setIntoFreeTime(15);
        carPark.setPayFreeTime(15);
        return carPark;
    }
}